package com.firemoss.validation
{
	import mx.collections.ArrayCollection;
	import mx.core.UIComponent;
	import mx.events.CollectionEvent;
	import mx.events.CollectionEventKind;
	import mx.events.FlexEvent;
	import mx.events.ValidationResultEvent;
	import mx.validators.Validator;

	public class ValidatorCollection extends ArrayCollection
	{
		
		// PRIVATE PROPERTIES
		
		private var invalidValidators : Array = [];
		
		// PUBLIC PROPERTIES
		
		[Bindable]
		public var hasErrors : Boolean = false
		
		override public function initialized(document:Object, id:String):void
		{
			super.initialized( document, id )
			
			if ( document is UIComponent )
			{
				// If declared in MXML, we'll end up adding our validators before their source properties have been set.
				UIComponent( document ).addEventListener( FlexEvent.CREATION_COMPLETE, documentCreated, false, 0, true )	
			}
		}
		
		override public function set source(s:Array):void
		{
			super.source = s
			
			itemsAdded( s )
		}


		// CONSTRUTCOR
		
		public function ValidatorCollection(source:Array=null)
		{
			super(source);
			
			addEventListener( CollectionEvent.COLLECTION_CHANGE, collectionChange, false, 0, true )
		}
		
		// PUBLIC METHODS

		
		public function validate() : void
		{
			for each ( var validator : Validator in this )
			{
				validator.validate()
			} 
		}
				
		// EVENT LISTENERS
		
		private function documentCreated( event : FlexEvent ) : void
		{
			itemsAdded( source )
		}
		
		private function collectionChange( event : CollectionEvent ) : void
		{
			switch ( event.type )
			{
				case CollectionEventKind.ADD:
					itemsAdded( event.items );
					break;
				case CollectionEventKind.REMOVE:
					itemsRemoved( event.items );
			}
		}
		
		protected function itemsAdded( items : Array ) : void
		{
			var validator : Validator
			
			for each ( validator in items )
			{
				if ( validator )
				{
					validator.addEventListener( ValidationResultEvent.INVALID, invalidValidation, false, 1, true )
					validator.addEventListener( ValidationResultEvent.VALID, validValidation, false, 1, true )
				}
			}
		}
		
		
		protected function itemsRemoved( items : Array ) : void
		{
			var validator : Validator
			
			for each ( validator in items )
			{
				if ( validator )
				{
					validator.removeEventListener( ValidationResultEvent.INVALID, invalidValidation )
					validator.removeEventListener( ValidationResultEvent.VALID, validValidation )
				}
			}
		}
		
		protected function invalidValidation( event : ValidationResultEvent ) : void
		{
			if ( invalidValidators.indexOf( event.target ) == - 1 )
			{
				invalidValidators.push( event.target )
			}
			
			hasErrors = invalidValidators.length > 0
		}
		
		protected function validValidation( event : ValidationResultEvent ) : void
		{
			if ( invalidValidators.indexOf( event.target ) != - 1 )
			{
				invalidValidators.splice( invalidValidators.indexOf( event.target ), 1 )
			}
			
			hasErrors = invalidValidators.length > 0
		}
		
	}
}